﻿using K3Cloud.WebApi.Core.IoC;
using K3Cloud.WebApi.Core.IoC.DataEntity;
using K3Cloud.WebApi.Core.IoC.Extensions;
using K3Cloud.WebApi.Core.IoC.K3Client;
using Newtonsoft.Json;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using WebDemo.Models.EntityTable;
using PRD_MO = FormEntityCreation.DataEntity.PRD_MO;

namespace IOCTestProject1
{
    public class Tests
    {
        [SetUp]
        public void Setup()
        {
            K3Services.AddK3Sugar(config =>
            {
                config.ServerHost = "http://localhost/k3cloud";
                config.AcctId = "61271b176f110c";
                config.UserName = "宋小康";
                config.AppID = "217311_Q6dO67sGTmmUQ5TKT27q7yXvzq2U5AOP";
                config.AppSecret = "b53e78db1bae4f859e2acb0de4d52552";
                config.LCID = 2052;
                config.ConnectionValidTime = 10;
            });
        }

        [Test]
        public void Unit1()
        {
            K3KeyValue kv = K3KeyValue.Parse("FName", "测试");
            K3KeyValue kv2 = "FName:测试";
            Assert.That(kv, Is.EqualTo(kv2));
        }

        [Test]
        public void Unit2()
        {
            string kvStr = "FName:测试";
            K3KeyValue result = kvStr;
            Assert.That(result, Is.EqualTo(K3KeyValue.Parse("FName", "测试")));
        }

        [Test]
        public void Unit3()
        {
            string kvStr = "FPrice|D:100.00";
            K3KeyValue result = kvStr;
            Assert.That(result, Is.EqualTo(K3KeyValue.Parse("FPrice", 100.00m)));
        }
        [Test]
        public void Unit4()
        {
            string kvStr = "d|FPrice:100.00";
            K3KeyValue result = kvStr;
            Assert.That(result, Is.EqualTo(K3KeyValue.Parse("FPrice", 100.00m)));
        }

        [Test]
        public void Unit5()
        {
            K3Number result = "001";
            Assert.That(result, Is.EqualTo(K3Number.Parse("001")));
        }

        [Test]
        public void Unit6()
        {
            K3User result = 100068;
            Assert.That(result, Is.EqualTo(K3User.Parse(100068)));
        }

        [Test]
        public void Query_ToJson()
        {
            string queryJson = K3Scoped.Client.Queryable<BD_Customer>()
                //.Where(t => new string[] { "001", "002" }.Contains(t.FNumber) && t.FChargeId__FName == "123" && t.FEMail.Contains("gmail.com"))
                .Where(t => t.FForbidStatus == "A")
                .OrderBy(t => new { t.FNumber, t.FSettleId__FName }, new OrderType[] { OrderType.Descending, OrderType.Ascending })
                .Take(5)
                .Select(t => new { t.FCUSTID, t.FCreatorId, t.FNumber, t.FName, t.FBankTypeRec__FNumber })
                //.Sum(t => t.FPRICELISTID__FNumber)
                //.Count(t => t.FNumber)
                .ToJson();
            Debug.WriteLine(queryJson);
            Assert.That(queryJson, Is.Not.Null);
        }
        /// <summary>
        /// 计数
        /// </summary>
        [Test]
        public void Query_Count()
        {
            string queryJson = K3Scoped.Client.Queryable<BD_Customer>()
                .Where(t => t.FForbidStatus == "A")
                .Count(t => t.FNumber)
                .ToJson();
            Debug.WriteLine(queryJson);
        }
        /// <summary>
        /// 汇总
        /// </summary>
        [Test]
        public void Query_Sum()
        {
            string queryJson = K3Scoped.Client.Queryable<WebDemo.Models.EntityTable.SAL_SaleOrder>()
                .Where(t => t.FBillNo == "XSDD00001")
                .Sum(t => t.FQty)
                .ToJson();
            Debug.WriteLine(queryJson);
        }

        [Test]
        public async Task Query1()
        {
            var query = await K3Scoped.Client.Queryable<BD_Customer>()
                .Where(t => true)
                .Select(t => new { t.FCUSTID, t.FCreatorId, t.FNumber, t.FName, t.FBankTypeRec__FNumber })
                .FirstAsync();
            Assert.That(query, Is.Not.Null);
        }

        [Test]
        public async Task SaveOrUpdate()
        {
            DateTime fDate = DateTime.Now;
            DateTime begDate = new(fDate.Year, fDate.Month, 1);
            DateTime endDate = begDate.AddMonths(1).AddDays(-1);
            BD_Rate rate = await K3Scoped.Client.Queryable<BD_Rate>().Where(t => t.FBegDate == begDate && t.FEndDate == endDate).FirstAsync();
            if (rate != null)
            {
                int Id = rate.FRateID;
                _ = await K3Scoped.Client.UnAuditAsync("BD_Rate", Id);
                decimal curRate = await HuilvAsync();
                K3SaveParam<BD_RateModel> bill = new()
                {
                    NeedUpDateFields = new string[] { "FExchangeRate", "FBegDate", "FEndDate" },
                    Model = new BD_RateModel
                    {
                        FRateID = Id,
                        FRATETYPEID = "HLTX01_SYS",
                        FCyForID = "PRE007",
                        FCyToID = "PRE001",
                        FExchangeRate = curRate,
                        FBegDate = begDate,
                        FEndDate = endDate,
                        FUseOrgId = "100",
                        FCreateOrgId = "100",
                    }
                };
                K3ApiResult<K3SaveResult> ret = await K3Scoped.Client.SaveAsync(bill, true);
            }
            else
            {
                decimal curRate = await HuilvAsync();
                if (curRate == 0)
                {
                    return;
                }

                K3SaveParam<BD_RateModel> bill = new()
                {
                    Model = new BD_RateModel
                    {
                        FRATETYPEID = "HLTX01_SYS",
                        FCyForID = "PRE007",
                        FCyToID = "PRE001",
                        FExchangeRate = curRate,
                        FBegDate = begDate,
                        FEndDate = endDate,
                        FUseOrgId = "100",
                        FCreateOrgId = "100",
                    }
                };
                K3ApiResult<K3SaveResult> ret = await K3Scoped.Client.SaveAsync(bill, true);
                if (ret == null)
                {
                    return;
                }
            }
        }

        /// <summary>
        /// 云星空单据查询json
        /// </summary>
        [Test]
        public void Unit7()
        {
            string jsonStr = K3Scoped.Client.Queryable<PUR_Requisition>().Where(t => t.FBillNo == "CGSQ000003").Select(t => new { t.FEntity_FEntryID }).ToJson();
            Debug.WriteLine(jsonStr);
        }

        /// <summary>
        /// 云星空表单保存json
        /// </summary>
        [Test]
        public void Unit8()
        {
            string dbId = "61271b176f110c";
            string userName = "宋小康";
            string appId = "217311_Q6dO67sGTmmUQ5TKT27q7yXvzq2U5AOP";
            string secret = "b53e78db1bae4f859e2acb0de4d52552";
            string lcId = "2052";
            long Timestamp = DateTimeFormatUtils.CurrentTimeSeconds();
            string[] arr = new string[] { dbId, userName, appId, secret, Timestamp.ToString() };
            string sign = KingdeeSignature.GetSignature(arr);
            string otherArgs = JsonConvert.SerializeObject(new
            {
                FormID = "PRD_PickMtrl",
                JsonType = "api",
                OpNumber = "Save",
                PK = "",
                OpenType = ""
            });
            otherArgs = otherArgs.Replace("\"", "'");
            var obj = new
            {
                dbid = dbId,
                username = userName,
                appid = appId,
                signeddata = sign,
                timestamp = Timestamp,
                lcid = lcId,
                origintype = "SimPas",
                entryrole = "HTML5",
                formid = "BOS_APIJsonWriter",
                formtype = "DynamicForm",
                pkid = "",
                openmode = "single",
                otherargs = otherArgs
            };
            string json = JsonConvert.SerializeObject(obj);
            string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
            string url = "http://192.168.1.3/k3cloud/html5/index.aspx?udencoding=utf-8&ud=" + base64;
            Debug.WriteLine(url);
        }

        /// <summary>
        /// 云星空修改json
        /// </summary>
        /// <returns></returns>
        [Test]
        public async Task Unit9()
        {
            PRD_PickMtrl bill = await K3Scoped.Client.Queryable<PRD_PickMtrl>().OrderBy(t => t.FID, new OrderType[1] { OrderType.Descending }).FirstAsync();

            string dbId = "61271b176f110c";
            string userName = "宋小康";
            string appId = "217311_Q6dO67sGTmmUQ5TKT27q7yXvzq2U5AOP";
            string secret = "b53e78db1bae4f859e2acb0de4d52552";
            string lcId = "2052";
            long Timestamp = DateTimeFormatUtils.CurrentTimeSeconds();
            string[] arr = new string[] { dbId, userName, appId, secret, Timestamp.ToString() };
            string sign = KingdeeSignature.GetSignature(arr);
            string otherArgs = JsonConvert.SerializeObject(new
            {
                FormID = bill.GetType().GetAlias(),
                JsonType = "api",
                OpNumber = "Save",
                PK = bill != null ? bill.FID.ToString() : "",
                OpenType = bill != null ? "Edit" : "New"
            });
            otherArgs = otherArgs.Replace("\"", "'");
            var obj = new
            {
                dbid = dbId,
                username = userName,
                appid = appId,
                signeddata = sign,
                timestamp = Timestamp,
                lcid = lcId,
                origintype = "SimPas",
                entryrole = "HTML5",
                formid = "BOS_APIJsonWriter",
                formtype = "DynamicForm",
                pkid = "",
                openmode = "single",
                otherargs = otherArgs
            };
            string json = JsonConvert.SerializeObject(obj);
            string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
            string url = "http://192.168.1.3/k3cloud/html5/index.aspx?udencoding=utf-8&ud=" + base64;
            Debug.WriteLine(url);
        }

        /// <summary>
        /// 云星空报表json
        /// </summary>
        [Test]
        public void Unit10()
        {
            string dbId = "61271b176f110c";
            string userName = "宋小康";
            string appId = "217311_Q6dO67sGTmmUQ5TKT27q7yXvzq2U5AOP";
            string secret = "b53e78db1bae4f859e2acb0de4d52552";
            string lcId = "2052";
            long Timestamp = DateTimeFormatUtils.CurrentTimeSeconds();
            string[] arr = new string[] { dbId, userName, appId, secret, Timestamp.ToString() };
            string sign = KingdeeSignature.GetSignature(arr);
            string otherArgs = JsonConvert.SerializeObject(new
            {
                FormID = "PUR_PurchasePriceAnalyzeRpt",
                JsonType = "api",
                OpNumber = "GetSysReportData",
                PK = "",
                OpenType = ""
            });
            otherArgs = otherArgs.Replace("\"", "'");
            var obj = new
            {
                dbid = dbId,
                username = userName,
                appid = appId,
                signeddata = sign,
                timestamp = Timestamp,
                lcid = lcId,
                origintype = "SimPas",
                entryrole = "HTML5",
                formid = "BOS_APIJsonWriter",
                formtype = "DynamicForm",
                pkid = "",
                openmode = "single",
                otherargs = otherArgs
            };
            string json = JsonConvert.SerializeObject(obj);
            string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
            string url = "http://192.168.1.3/k3cloud/html5/index.aspx?udencoding=utf-8&ud=" + base64;
            Debug.WriteLine(url);
        }

        [Test]
        public async Task Unit11()
        {
            string formId = "PUR_PurchasePriceAnalyzeRpt";
            string json = @"{
                ""FieldKeys"": ""FPURCHASEORGID,FSUPPLIERID,FMATERIALID,FMATERIALGROUPNAME,FPRICELISTPRICE,FPRICEUNITID,FLatestPrice,FHighestPrice,FLowestPrice,FAveragePrice,FHugestVolumePrice,FSmallestVolumePrice,FAnnualHighestPrice,FAnnualLowestPrice,FAnnualAveragePrice,FMaterialCategoryName,FDISCOUNTRATE,FPredictPrice,FMATERIALNUMBER,FSPECIFICATION,FPRICESOURCE,FBUSINESSTYPENAME,FPRICELISTCURR,FAuxPropId,FUNITBASE,FCURRENCYNAME,FBASEUNITQTY,FCURRENCYAMOUNT,FCURRENCYALLAMOUNT"",
                ""SchemeId"": """",
                ""StartRow"": 0,
                ""Limit"": 2000,
                ""IsVerifyBaseDataField"": ""true"",
                ""Model"": {
                    ""FPurchaseOrgIdList"": ""1"",
                    ""FBeginDate"": ""2023-01-01 00:00:00"",
                    ""FEndDate"": ""2023-08-28 00:00:00"",
                    ""FBeginMaterialCategory"": {
                        ""FNUMBER"": ""CHLB01_SYS""
                    },
                    ""FEndMaterialCategory"": {
                        ""FNUMBER"": ""CHLB01_SYS""
                    },
                    ""FBusinessType"": ""CG"",
                    ""FPriceDimension"": ""Material"",
                    ""FPriceSource"": ""PurchaseOrder"",
                    ""FAveragePriceType"": ""MovingAveragePrice"",
                    ""FIsIncludeTax"": true,
                    ""FDocumentStatus"": ""C""
                }
            }";
            string result = await K3Scoped.Client.GetSysReportDataAsync(formId, json);
            Debug.WriteLine(result);
        }

        /// <summary>
        /// IN的表达式拼接
        /// </summary>
        [Test]
        public void Unit12()
        {
            Type t = typeof(int);
            dynamic array = ExpTmpFieldDynamicCall(t, "1,2,3");
            ParameterExpression parameters = Expression.Parameter(typeof(BD_Rate), "t");
            MemberExpression property = Expression.PropertyOrField(parameters, "FRateID");
            MethodInfo MethodContains = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                    .Single(m => m.Name == nameof(Enumerable.Contains) && m.GetParameters().Length == 2).MakeGenericMethod(t);
            dynamic constant = Expression.Constant(array);
            FieldInfo fieldInfo = array.ArrFieldInfo();
            MethodCallExpression call = Expression.Call(null, MethodContains, new Expression[2] { Expression.Field(constant, fieldInfo), property });
            Expression<Func<BD_Rate, bool>> expression = Expression.Lambda<Func<BD_Rate, bool>>(call, parameters);
            SQLBuilder.Entry.SqlBuilderCore<BD_Rate> build = SQLBuilder.Entry.SqlBuilder.Select<BD_Rate>().Where(expression);
            Dictionary<string, object> param = build.Parameters;
            string sql = build.Sql;
            Debug.WriteLine(sql);
            // 等效表达式
            int[] array1 = new int[] { 1, 2, 3 };
            Expression<Func<BD_Rate, bool>> expression1 = t => array1.Contains(t.FRateID);
            SQLBuilder.Entry.SqlBuilderCore<BD_Rate> build2 = SQLBuilder.Entry.SqlBuilder.Select<BD_Rate>().Where(expression1);
            Dictionary<string, object> param2 = build2.Parameters;
            string sql2 = build2.Sql;
            Debug.WriteLine(sql2);
            using (Assert.EnterMultipleScope())
            {
                Assert.That(sql, Is.EqualTo("SELECT * FROM BD_Rate WHERE FRateID IN (@p__1,@p__2,@p__3)"));
                Assert.That(sql2, Is.EqualTo("SELECT * FROM BD_Rate WHERE FRateID IN (@p__1,@p__2,@p__3)"));
                Assert.That(param["@p__1"], Is.EqualTo(1));
                Assert.That(param2["@p__1"], Is.EqualTo(1));
            }
        }

        /// <summary>
        /// 生产订单下推生产入库单
        /// </summary>
        [Test]
        public async Task Unit13()
        {
            PRD_MO moEntity = await K3Scoped.Client.Queryable<PRD_MO>(t => t.FStatus == "4").FirstAsync();
            if (moEntity == null)
            {
                return;
            }

            K3ApiResult<K3SaveResult> result = await K3Scoped.Client.PushAsync("PRD_MO", moEntity.FTreeEntity_FEntryId.ToString(), "PRD_MO2INSTOCK");
        }


        [Test]
        public async Task Unit14()
        {
            Expression<Func<BD_MATERIAL, bool>> expression = t => t.FErpClsID == EnumErpCls.自制;
            List<BD_MATERIAL> moEntity = await K3Scoped.Client.Queryable<BD_MATERIAL>().Where(expression).ToListAsync();
        }

        [Test]
        public async Task Unit15()
        {
            bool b = false;
            Expression<Func<BD_MATERIAL, bool>> expression = t => t.FErpClsID == EnumErpCls.自制 && t.FModel == "木柄" || t.FIsSale == b;
            var str = ExpressionBuilder.GetFilterString(expression);
            Debug.WriteLine(str);
            await Task.CompletedTask;
        }

        [Test]
        public async Task Unit16()
        {
            var str = K3Scoped.Client.Queryable<BD_Rate>().Select(t => new { t.FEndDate, t.FExchangeRate }).Count(t => t.FEndDate).ToJson();
            Debug.WriteLine(str);
            await Task.CompletedTask;
        }

        #region 私有方法

        /// <summary>
        /// 将input转换为dynamic类型数组
        /// </summary>
        private static dynamic ExpTmpFieldDynamicCall(Type type, string input)
        {
            try
            {
                MethodInfo method = typeof(ExpTmpField<>).MakeGenericType(type).GetMethod("Parse");
                return method.Invoke(null, new object[] { input });
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 提取有效的美元汇率
        /// </summary>
        /// <returns></returns>
        private static async Task<decimal> HuilvAsync()
        {
            DateTime fDate = DateTime.Today;
            DateTime begDate = new(fDate.Year, fDate.Month, 1);
            string findStr = "1美元对人民币";
            string endStr = "元，";
            string content = await GetHuilvGongGaoAsync(begDate);
            int startIndex = content.IndexOf(findStr);
            if (startIndex == -1)
            {
                return 0;
            }

            int endIndex = content.IndexOf(endStr, startIndex);
            string result = content.Substring(startIndex + findStr.Length, endIndex - startIndex - findStr.Length);
            decimal resultNumber = decimal.Parse(result);
            Console.WriteLine("美元对人民币汇率: " + resultNumber);
            return resultNumber;
        }

        /// <summary>
        /// 中国外汇交易中心受权公布人民币汇率中间价公告
        /// </summary>
        /// <param name="begDate">日期</param>
        /// <returns></returns>
        private static async Task<string> GetHuilvGongGaoAsync(DateTime begDate)
        {
            using HttpClient client = new();
            client.Timeout = TimeSpan.FromSeconds(5);
            string Url = $"http://www.chinamoney.com.cn/r/cms/www/chinamoney/data/fx/ccpr-notice{begDate:yyyy-MM-dd}.json";
            HttpResponseMessage result = await client.GetAsync(Url);
            while (result.StatusCode != System.Net.HttpStatusCode.OK)
            {
                begDate = begDate.AddDays(1);
                if (begDate > DateTime.Today.AddDays(1))
                {
                    break;
                }
                Url = $"http://www.chinamoney.com.cn/r/cms/www/chinamoney/data/fx/ccpr-notice{begDate:yyyy-MM-dd}.json";
                result = await client.GetAsync(Url);
            }
            string content = await result.Content.ReadAsStringAsync();
            return content;
        }
        #endregion
    }
}